﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Kugar.Core.Exceptions;
using Kugar.Core.ExtMethod;
using Kugar.Tools.IM.Tencent.ServerSDK.Enums;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

namespace Kugar.Tools.IM.Tencent.ServerSDK.Converts
{
    public class IMMessageJsonConverter : JsonConverter
    {
        public override bool CanConvert(Type objectType)
        {
            return objectType == typeof(IMMessageBase) || objectType.IsSubclassOf(typeof(IMMessageBase));
        }

        public override object ReadJson(JsonReader reader, Type objectType, object existingValue,
            JsonSerializer serializer)
        {
            var json = JObject.Load(reader);

            var type = Until.GetMessageTypeFromStr(json.GetString("MsgType"));
            var content = json.GetJObject("MsgContent");

            switch (type)
            {
                case MessageItemTypeEnum.Text:
                    return new Message_Text(content.GetString("Text"));
                case MessageItemTypeEnum.Face:
                    return new Message_Face(content.GetInt("Index"), content.GetString("Data"));
                case MessageItemTypeEnum.Image:
                {
                    var item = new Message_Image();
                    item.UUID = content.GetString("UUID");
                    item.Format = content.GetInt("ImageFormat");

                    foreach (var imageJson in content.GetJObjectArray("ImageInfoArray"))
                    {
                        var imageType = imageJson.GetInt("Type");
                        var imageData = new Message_Image.ImageItem();

                        imageData.Height = imageJson.GetInt("Height");
                        imageData.Width = imageJson.GetInt("Width");
                        imageData.Size = imageJson.GetInt("Size");
                        imageData.Url = imageJson.GetString("URL");

                        switch (imageType)
                        {
                            case 1:
                            {
                                item.SourceImage = imageData;
                                break;
                            }
                            case 2:
                            {
                                item.LargeImage = imageData;
                                break;
                            }
                            case 3:
                            {
                                item.Thumbnail = imageData;
                                break;
                            }
                        }
                    }

                    return item;
                }
                case MessageItemTypeEnum.Sound:
                {
                    return new Message_Sound(content.GetString("UUID"), content.GetInt("Size"),
                        content.GetInt("Second"));
                }
                case MessageItemTypeEnum.File:
                {
                    return new Message_File(content.GetString("UUID"), content.GetInt("FileSize"),
                        content.GetString("FileName"));
                }
                case MessageItemTypeEnum.Custom:
                    break;
                case MessageItemTypeEnum.Location:
                    break;
                default:
                    throw new ArgumentOutOfRangeException();
            }

            return null;
        }

        public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
        {
            var msg = (IMMessageBase) value;

            if (msg == null)
            {
                throw new ArgumentTypeNotMatchException(nameof(value), "IMMessageBase");
            }

            writer.WriteStartObject();

            writer.WriteProperty("MsgType", Until.GetMessageTypeStr(msg.Type));
            writer.WritePropertyName("MsgContent");

            writer.WriteStartObject();

            switch (msg)
            {
                case Message_Text textMsg:
                    writer.WriteProperty("Text", textMsg.Text);
                    break;
                case Message_Face faceMsg:
                {
                    writer.WriteProperty("Index", faceMsg.Index)
                        .WriteProperty("Data", faceMsg.Data);
                }
                    break;
                case Message_Image imgMsg:
                {
                    writer.WriteProperty("UUID", imgMsg.UUID)
                        .WriteProperty("ImageFormat", imgMsg.Format);

                    writer.WritePropertyName("ImageInfoArray");
                    writer.WriteStartArray();

                    if (imgMsg.SourceImage != null)
                    {
                        writer.WriteStartObject();
                        writer.WriteProperty("Type", 1)
                            .WriteProperty("Size", imgMsg.SourceImage.Size)
                            .WriteProperty("Width", imgMsg.SourceImage.Width)
                            .WriteProperty("Height", imgMsg.SourceImage.Height)
                            .WriteProperty("URL", imgMsg.SourceImage.Url);
                        writer.WriteEndObject();
                    }

                    if (imgMsg.LargeImage != null)
                    {
                        writer.WriteStartObject();
                        writer.WriteProperty("Type", 2)
                            .WriteProperty("Size", imgMsg.LargeImage.Size)
                            .WriteProperty("Width", imgMsg.LargeImage.Width)
                            .WriteProperty("Height", imgMsg.LargeImage.Height)
                            .WriteProperty("URL", imgMsg.LargeImage.Url);
                        writer.WriteEndObject();
                    }

                    if (imgMsg.Thumbnail != null)
                    {
                        writer.WriteStartObject();
                        writer.WriteProperty("Type", 3)
                            .WriteProperty("Size", imgMsg.Thumbnail.Size)
                            .WriteProperty("Width", imgMsg.Thumbnail.Width)
                            .WriteProperty("Height", imgMsg.Thumbnail.Height)
                            .WriteProperty("URL", imgMsg.Thumbnail.Url);
                        writer.WriteEndObject();
                    }

                    writer.WriteEndArray();
                }
                    break;
                case Message_Sound soundMsg:
                {
                    writer.WriteProperty("UUID", soundMsg.UUID)
                        .WriteProperty("Size", soundMsg.Size)
                        .WriteProperty("Second", soundMsg.Second);
                }
                    break;
                case Message_File fileMsg:
                {
                    writer.WriteProperty("UUID", fileMsg.UUID)
                        .WriteProperty("FileSize", fileMsg.Size)
                        .WriteProperty("FileName", fileMsg.Url);

                }
                    break;
                default:
                    throw new ArgumentOutOfRangeException();
            }

            writer.WriteEndObject();

            writer.WriteEndObject();
        }
    }
}